package com.bihua.iot.service.impl;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bihua.common.core.domain.PageQuery;
import com.bihua.common.core.page.TableDataInfo;
import com.bihua.common.exception.ServiceException;
import com.bihua.common.utils.StringUtils;
import com.bihua.iot.domain.DeviceCommands;
import com.bihua.iot.domain.bo.DeviceCommandsBo;
import com.bihua.iot.domain.vo.DeviceCommandsVo;
import com.bihua.iot.domain.vo.ProductCommandsVo;
import com.bihua.iot.domain.vo.ProductServicesVo;
import com.bihua.iot.mapper.DeviceCommandsMapper;
import com.bihua.iot.service.IDeviceCommandsService;
import com.bihua.iot.service.IProductCommandsService;
import com.bihua.iot.service.IProductServicesService;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 设备动作Service业务层处理
 *
 * @author bihua
 * @date 2023-07-23
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class DeviceCommandsServiceImpl implements IDeviceCommandsService {

    private final DeviceCommandsMapper baseMapper;
    private final IProductServicesService iProductServicesService;
    private final IProductCommandsService iProductCommandsService;
    /**
     * 查询设备动作
     */
    @Override
    public DeviceCommandsVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询设备动作列表
     */
    @Override
    public TableDataInfo<DeviceCommandsVo> queryPageList(DeviceCommandsBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<DeviceCommands> lqw = buildQueryWrapper(bo);
        Page<DeviceCommandsVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询设备动作列表
     */
    @Override
    public List<DeviceCommandsVo> queryList(DeviceCommandsBo bo) {
        LambdaQueryWrapper<DeviceCommands> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<DeviceCommands> buildQueryWrapper(DeviceCommandsBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<DeviceCommands> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceIdentification()), DeviceCommands::getDeviceIdentification, bo.getDeviceIdentification());
        lqw.eq(bo.getServiceId() != null, DeviceCommands::getServiceId, bo.getServiceId());
        lqw.eq(bo.getCommandId() != null, DeviceCommands::getCommandId, bo.getCommandId());
        lqw.eq(StringUtils.isNotBlank(bo.getCommandRequest()), DeviceCommands::getCommandRequest, bo.getCommandRequest());
        lqw.eq(StringUtils.isNotBlank(bo.getCommandResponse()), DeviceCommands::getCommandResponse, bo.getCommandResponse());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), DeviceCommands::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增设备动作
     */
    @Override
    public Boolean insertByBo(DeviceCommandsBo bo) {
        DeviceCommands add = BeanUtil.toBean(bo, DeviceCommands.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            JSONObject commandRequest = JSONUtil.parseObj(add.getCommandRequest());
            commandRequest.set("mid", add.getId());
            baseMapper.updateCommandRequestById(commandRequest.toString(), add.getId());
        }
        return flag;
    }

    /**
     * 修改设备动作
     */
    @Override
    public Boolean updateByBo(DeviceCommandsBo bo) {
        DeviceCommands update = BeanUtil.toBean(bo, DeviceCommands.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DeviceCommands entity){
        //TODO 做一些数据校验,如唯一约束
        ProductServicesVo productServicesVo = iProductServicesService.queryById(entity.getServiceId());
        if(ObjectUtil.isNull(productServicesVo)){
            log.error("The product service is not exist,serviceId:{}", entity.getServiceId());
            throw new ServiceException("服务不已存在!");
        }
        ProductCommandsVo productCommandsVo = iProductCommandsService.queryById(entity.getCommandId());
        if(ObjectUtil.isNull(productCommandsVo)){
            log.error("The product command is not exist,commandId:{}", entity.getCommandId());
            throw new ServiceException("命令不已存在!");
        }
        JSONObject commandRequest = JSONUtil.parseObj(entity.getCommandRequest());
        if(!StringUtils.equalsIgnoreCase(productServicesVo.getServiceName(), (String)commandRequest.get("serviceId"))){
            log.error("The serviceId is inconsistent,serviceId:{}, commandRequest:{}", entity.getServiceId(), entity.getCommandRequest());
            throw new ServiceException("命令内容serviceId不正确!");
        }
        if(!StringUtils.equalsIgnoreCase(productCommandsVo.getName(), (String)commandRequest.get("cmd"))){
            log.error("The commandId is inconsistent,commandId:{}, commandRequest:{}", entity.getCommandId(), entity.getCommandRequest());
            throw new ServiceException("命令内容cmd不正确!");
        }
    }

    /**
     * 批量删除设备动作
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public Boolean updateStatusById(String status, Long id) {
        return baseMapper.updateStatusById(status, id) > 0;
    }

    @Override
    public Boolean updateCommandResponseById(String commandResponse, String status, Long id) {
        return baseMapper.updateCommandResponseById(commandResponse, status, id) > 0;
    }
}
